package com.chebaohui.iqs.mapper.sql;

import java.lang.reflect.Field;

import org.apache.ibatis.jdbc.SQL;

import com.chebaohui.iqs.sdk.DBColumn;
import com.chebaohui.iqs.sdk.DBTable;

/**
 * ClassName: SqlProvider<br>
 * Description: 数据库操作基础sql语句 .<br>
 * 所有的语句生成 需要动态传入对象
 *
 * @author Sean
 * @date: 2016年11月14日 下午7:04:32
 * @version V1.0
 * @since JDK 1.8
 * @param <T>
 */
public class Provider<T> {

	/**
	 * 数据新增语句
	 * 
	 * @param t
	 * @return
	 * @throws Exception
	 */
	public String insert(final T t) throws Exception {
		return new SQL() {
			{

				String table = getTableName(t);
				if (null == table) {
					throw new Exception("Insert the Object annotation " + DBTable.class);
				}
				// 装载新增表名
				INSERT_INTO(table);
				// 装载列
				// 装载计数
				int count = 0;
				for (Field field : t.getClass().getDeclaredFields()) {
					String values = null;
					// 获取变量值
					values = getValues(field, t);
					// 为空 不参与更新
					if (null == values) {
						continue;
					}
					// 只有变量声明注解的 才会纳入解析
					if (!field.isAnnotationPresent(DBColumn.class)) {
						continue;
					}
					String columns = null;
					// 获取变量注解
					DBColumn column = field.getAnnotation(DBColumn.class);
					// 获取变量名
					columns = getColumns(column, field);
					VALUES(columns, "#{" + field.getName() + "}");
					count++;
				}
				// 对象数据为null 或者没有使用注解
				if (0 == count) {
					throw new Exception(
							"Insert the Object`s variables is null or is not use annotation " + DBColumn.class);
				}

			}
		}.toString();
	}

	/**
	 * 数据删除语句
	 * 
	 * @param t
	 * @return
	 * @throws Exception
	 */
	public String delete(final T t) throws Exception {
		return new SQL() {
			{
				String table = getTableName(t);
				if (null == table) {
					throw new Exception("Delect the Object annotation " + DBTable.class);
				}
				// 装载删除表名
				DELETE_FROM(table);
				// 装载主键
				int count = 0;
				for (Field field : t.getClass().getDeclaredFields()) {
					String values = null;
					values = getValues(field, t);
					// 值为空 则无法删除
					if (null == values) {
						continue;
					}
					// 只有变量声明注解的 才会纳入解析
					if (!field.isAnnotationPresent(DBColumn.class)) {
						continue;
					}
					String columns = null;
					// 获取变量注解
					DBColumn column = field.getAnnotation(DBColumn.class);
					// 获取变量名
					columns = getPrimary(column, field);
					// 为空 则不是主键
					if (null == columns) {
						continue;
					}
					// 获取变量值
					WHERE(columns + " = #{" + field.getName() + "}");
					count++;
					break;
				}
				// 对象数据为null 或者没有使用注解
				if (0 == count) {
					throw new Exception(
							"Delect the Object`s variables is null or is not use annotation " + DBColumn.class);
				}

			}
		}.toString();
	}

	/**
	 * 数据更新语句
	 * 
	 * @param t
	 * @return
	 * @throws Exception
	 */
	public String update(final T t) throws Exception {
		return new SQL() {
			{
				String table = getTableName(t);
				if (null == table) {
					throw new Exception("update the Object annotation " + DBTable.class);
				}
				// 装载更新表名
				UPDATE(table);
				int count = 0;
				boolean hasPrimary = false;
				for (Field field : t.getClass().getDeclaredFields()) {
					String values = null;
					values = getValues(field, t);
					// 值为空 则无法删除
					if (null == values) {
						continue;
					}
					// 只有变量声明注解的 才会纳入解析
					if (!field.isAnnotationPresent(DBColumn.class)) {
						continue;
					}
					String columns = null;
					// 获取变量注解
					DBColumn column = field.getAnnotation(DBColumn.class);
					// 获取变量名
					columns = getColumns(column, field);
					// 为空 则不需要更新
					if (null != columns && !column.primary() && !column.foreign()) {
						// 获取变量值
						SET(columns + " = #{" + field.getName() + "}");
					}
					// 获取变量名
					columns = getPrimary(column, field);
					// 为空 则不是主键
					if (null != columns) {
						hasPrimary = true;
						// 获取变量值
						WHERE(columns + " = #{" + field.getName() + "}");
					}
					count++;
				}
				// 对象数据为null 或者没有使用注解
				if (0 == count) {
					throw new Exception(
							"update the Object`s variables is null or is not use annotation " + DBColumn.class);
				}
				if (!hasPrimary) {
					throw new Exception("update mast be have primary");
				}

			}
		}.toString();
	}

	public String updateByForeign(final T t) throws Exception {
		return new SQL() {
			{
				String table = getTableName(t);
				if (null == table) {
					throw new Exception("Delect the Object annotation " + DBTable.class);
				}
				// 装载更新表名
				UPDATE(table);
				int count = 0;
				boolean hasForeign = false;
				for (Field field : t.getClass().getDeclaredFields()) {
					String values = null;
					values = getValues(field, t);
					// 值为空 则无法删除
					if (null == values) {
						continue;
					}
					// 只有变量声明注解的 才会纳入解析
					if (!field.isAnnotationPresent(DBColumn.class)) {
						continue;
					}
					String columns = null;
					// 获取变量注解
					DBColumn column = field.getAnnotation(DBColumn.class);
					// 获取变量名
					columns = getColumns(column, field);
					// 为空或主键外键 则不需要更新
					if (null != columns && !column.primary() && !column.foreign()) {
						// 获取变量值
						SET(columns + " = #{" + field.getName() + "}");
					}
					// 获取变量名
					columns = getForeign(column, field);
					// 为空 则不是外键
					if (null != columns) {
						hasForeign = true;
						// 获取变量值
						WHERE(columns + " = #{" + field.getName() + "}");
					}
					count++;
				}
				// 对象数据为null 或者没有使用注解
				if (0 == count) {
					throw new Exception("updateByForeign the Object`s variables is null or is not use annotation "
							+ DBColumn.class);
				}
				if (!hasForeign) {
					throw new Exception("updateByForeign mast be have foreign");
				}

			}
		}.toString();
	}

	/**
	 * 通用非空未禁用更新语句
	 * 
	 * @param t
	 * @return
	 * @throws Exception
	 */
	public String updateNullDisable(final T t) throws Exception {
		return new SQL() {
			{
				String table = getTableName(t);
				if (null == table) {
					throw new Exception("Delect the Object annotation " + DBTable.class);
				}
				// 装载更新表名
				UPDATE(table);
				int count = 0;
				boolean hasPrimary = false;
				for (Field field : t.getClass().getDeclaredFields()) {
					String values = null;
					values = getValues(field, t);
					// 值为空 则无法删除
					if (null == values) {
						continue;
					}
					// 只有变量声明注解的 才会纳入解析
					if (!field.isAnnotationPresent(DBColumn.class)) {
						continue;
					}
					String columns = null;
					// 获取变量注解
					DBColumn column = field.getAnnotation(DBColumn.class);
					// 获取变量名
					columns = getColumns(column, field);
					// 为空 则不需要更新
					if (null != columns && true == column.update()) {
						// 获取变量值
						SET(columns + " = #{" + field.getName() + "}");
					}
					// 获取变量名
					columns = getPrimary(column, field);
					// 为空 则不是主键
					if (null != columns) {
						hasPrimary = true;
						// 获取变量值
						WHERE(columns + " = #{" + field.getName() + "}");
					}
					count++;
				}
				// 对象数据为null 或者没有使用注解
				if (0 == count) {
					throw new Exception("updateNullDisable the Object`s variables is null or is not use annotation "
							+ DBColumn.class);
				}
				if (!hasPrimary) {
					throw new Exception("updateNullDisable mast be have primary");
				}

			}
		}.toString();
	}

	/**
	 * 通用查询一条数据语句
	 * 
	 * @param t
	 * @return
	 * @throws Exception
	 */
	public String queryOne(final T t) throws Exception {
		String string = new SQL() {
			{
				int count = 0;
				StringBuffer buffer = new StringBuffer();
				for (Field field : t.getClass().getDeclaredFields()) {
					// 只有变量声明注解的 才会纳入解析
					if (!field.isAnnotationPresent(DBColumn.class)) {
						continue;
					}
					if (buffer.length() > 0) {
						buffer.append(",");
					}
					String columns = null;
					// 获取变量注解
					DBColumn column = field.getAnnotation(DBColumn.class);
					// 获取变量名
					columns = getPrimary(column, field);
					// 为空 则不是主键
					if (null != columns) {
						String values = null;
						// 获取属性值
						values = getValues(field, t);
						// 值为空 则无法删除
						if (null == values) {
							continue;
						}
						count++;
						// 获取变量值
						WHERE(columns + " = #{" + field.getName() + "}");
					}
					// 获取变量名
					columns = getColumn(column, field);
					// 为空 跳出
					if (null == columns) {
						continue;
					}
					if ("".equals(columns)) {
						buffer.append(field.getName());
					} else {
						buffer.append(columns + " as " + field.getName());
					}
				}
				// 计数为0 则无条件 字段为长度为0 不是正确的实体类
				if (0 == count || buffer.length() == 0) {
					throw new Exception(
							"queryOne the Object`s variables is null or is not use annotation " + DBColumn.class);
				}

				// 装载查询字段
				SELECT(buffer.toString());
				String table = getTableName(t);
				if (null == table) {
					throw new Exception("Delect the Object annotation " + DBTable.class);
				}

				// 装载查询表名
				FROM(table);

			}
		}.toString();
		return string;
	}

	/**
	 * 通用主键列表查询语句
	 * 
	 * @param t
	 * @return
	 * @throws Exception
	 */
	public String queryIdByParam(final T t) throws Exception {
		return new SQL() {
			{
				// 排序按照主键 主键为有序增长
				String orderBy = null;
				String string = null;
				for (Field field : t.getClass().getDeclaredFields()) {
					// 只有变量声明注解的 才会纳入解析
					if (!field.isAnnotationPresent(DBColumn.class)) {
						continue;
					}
					String columns = null;
					String values = null;
					// 获取变量注解
					DBColumn column = field.getAnnotation(DBColumn.class);
					// 获取变量名
					columns = getColumn(column, field);
					// 为空 跳出
					if (null == columns) {
						continue;
					}
					if (column.primary()) {
						if ("".equals(columns)) {
							string = field.getName();
						} else {
							string = columns + " as " + field.getName();
						}
					}

					// 获取属性值
					values = getValues(field, t);
					// 为空 则不是主键
					if (null != values) {
						if ("".equals(columns)) {
							columns = field.getName();
						}
						// 获取变量值
						WHERE(columns + " = #{" + field.getName() + "}");
					}
					columns = getPrimary(column, field);
					if (null != columns) {
						orderBy = columns + " DESC";
					}

				}

				// 装载查询字段
				SELECT(string);
				String table = getTableName(t);
				if (null == table) {
					throw new Exception("Delect the Object annotation " + DBTable.class);
				}

				// 装载查询表名
				FROM(table);

				if (null != orderBy) {
					ORDER_BY(orderBy);
				}
			}
		}.toString();
	}

	/**
	 * 通用全查语句注解生成
	 * 
	 * @param t
	 * @return
	 * @throws Exception
	 */
	public String queryAll(final T t) throws Exception {
		String string = new SQL() {
			{
				// 排序按照主键 主键为有序增长
				StringBuffer buffer = new StringBuffer();
				// 排序按照主键 主键为有序增长
				String orderBy = null;
				for (Field field : t.getClass().getDeclaredFields()) {
					// 只有变量声明注解的 才会纳入解析
					if (!field.isAnnotationPresent(DBColumn.class)) {
						continue;
					}
					if (buffer.length() > 0) {
						buffer.append(",");
					}
					String columns = null;
					String values = null;
					// 获取变量注解
					DBColumn column = field.getAnnotation(DBColumn.class);
					// 获取变量名
					columns = getColumn(column, field);
					// 为空 跳出
					if (null == columns) {
						continue;
					}
					if ("".equals(columns)) {
						columns = field.getName();
						buffer.append(columns);
					} else {
						buffer.append(columns + " as " + field.getName());
					}
					// 获取属性值
					values = getValues(field, t);
					// 为空 则不是主键
					if (null != values) {
						// 获取变量值
						WHERE(columns + " = #{" + field.getName() + "}");
					}
					if (column.orderBy()) {
						if (null != orderBy && orderBy.lastIndexOf(",") != orderBy.length()) {
							ORDER_BY(orderBy);
						} else {
							orderBy = columns + " " + column.sort();
						}
					}
				}
				// 装载查询字段
				SELECT(buffer.toString());
				String table = getTableName(t);
				if (null == table) {
					throw new Exception("Delect the Object annotation " + DBTable.class);
				}
				// 装载查询表名
				FROM(table);

			}
		}.toString();
		// System.out.println(string);
		return string;
	}

	/**
	 * 通用分页语句
	 * 
	 * @param t
	 * @param start
	 * @param length
	 * @return
	 * @throws Exception
	 */
	public String queryLimit(final T t, Integer start, Integer length) throws Exception {
		String sql = new SQL() {
			{

				String table = getTableName(t);
				if (null == table) {
					throw new Exception("queryLimit the Object annotation " + DBTable.class);
				}

				// 装载查询表名
				FROM(table);
				// 排序按照主键 主键为有序增长
				String orderBy = null;
				for (Field field : t.getClass().getDeclaredFields()) {
					// 只有变量声明注解的 才会纳入解析
					if (!field.isAnnotationPresent(DBColumn.class)) {
						continue;
					}
					String columns = null;
					String values = null;
					// 获取变量注解
					DBColumn column = field.getAnnotation(DBColumn.class);
					// 获取变量名
					columns = getColumn(column, field);
					// 为空 跳出
					if (null == columns) {
						continue;
					}
					if ("".equals(columns)) {
						columns = field.getName();
						SELECT(columns);
					} else {
						SELECT(columns + " AS " + field.getName());
					}
					// 获取属性值
					values = getValues(field, t);
					// 为空 则不是主键
					if (null != values) {
						// 获取变量值
						WHERE(columns + " = #{T." + field.getName() + "} ");
					}
					if (column.orderBy()) {
						if (null != orderBy && orderBy.lastIndexOf(",") != orderBy.length()) {
							ORDER_BY(orderBy);
						} else {
							orderBy = columns + " " + column.sort();
						}
					}

				}

				if (null != orderBy) {
					ORDER_BY(orderBy.concat(" LIMIT").concat(" " + (start - 1) * length).concat("," + length));
				}
			}
		}.toString();
		return sql;
	}

	/**
	 * 获取表名
	 * 
	 * @param t
	 * @return
	 */
	protected String getTableName(T t) {
		// 获取实体类注解
		DBTable dbTable = t.getClass().getAnnotation(DBTable.class);
		// 如果实体类没有注解 返回null
		if (null == dbTable) {
			return null;
		}
		// 如果没有设置表名 则取类名
		if (null == dbTable.name() || "".equals(dbTable.name().trim())) {
			return t.getClass().getSimpleName();
		}
		return dbTable.name();
	}

	/**
	 * 获取列名
	 * 
	 * @param field
	 * @param column
	 * @return
	 */
	protected String getColumns(DBColumn column, Field field) {
		// 获取变量注解
		if (null == column) {
			return null;
		}
		// 如果只是声明没有值 则用变量名
		if (null == column.column() || "".equals(column.column().trim())) {
			return field.getName();
		}
		return column.column();
	}

	protected String getColumn(DBColumn column, Field field) {
		// 获取变量注解
		if (null == column) {
			return null;
		}
		return column.column();
	}

	/**
	 * 获取主键
	 * 
	 * @param column
	 * @param field
	 * @return
	 */
	protected String getPrimary(DBColumn column, Field field) {
		// 获取变量注解
		if (null == column || !column.primary()) {
			return null;
		}
		// 如果只是声明没有值 则用变量名
		if (null == column.column() || "".equals(column.column().trim())) {
			return field.getName();
		}
		return column.column();
	}

	/**
	 * 外键
	 * 
	 * @param column
	 * @param field
	 * @return
	 */
	protected String getForeign(DBColumn column, Field field) {
		// 获取变量注解
		if (null == column || !column.foreign()) {
			return null;
		}
		// 如果只是声明没有值 则用变量名
		if (null == column.column() || "".equals(column.column().trim())) {
			return field.getName();
		}
		return column.column();
	}

	/**
	 * 根据属性获取值
	 * 
	 * @param field
	 * @param t
	 * @return
	 * @throws IllegalArgumentException
	 * @throws IllegalAccessException
	 */
	protected String getValues(Field field, T t) throws IllegalArgumentException, IllegalAccessException {
		if (null == field) {
			return null;
		}
		if (null == t) {
			return null;
		}
		field.setAccessible(true); // 设置些属性是可以访问的
		Object value = field.get(t);
		// 如果值为空 直接返回
		if (null == value) {
			return null;
		}
		return value.toString();
	}

}
